package com.kyk.util;

import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtUtils {

    private String jwtSecret = "qfVfD7j8kL3mN5pR9sT2uW4xZ6yB8cE0dG2fH4iJ6kL8mN0oP2qR4sT6uV8wX0yZ2b4c6d8f0g2h4i6j8k+l0m2n4o6p8q/r1s3t5u7v9w/x2y4z6A8B0C2D4E6F8G0H2I4J6K8L+M0N2O4P6Q8R0S2T4U6V8W0X2Y4Z6a8b0c2d4e6f8g0h2i4j6k8l+m0n2o4p6q8r/s1t3u5v7w9x/y2z4A6B8C0D2E4F6G8H0I2J4K6L8M+N0O2P4Q6R8S0T2U4V6W8X0Y2Z4a6b8c0d2e4f6g8h0i2j4k6l8m/n0o2p4q6r8s/t1u3v5w7x9y/z2A4B6C8D0E2F4G6H8I0J2K4L6M8N+O0P2Q4R6S8T0U2V4W6X8Y0Z2a4b6c8d0e2f4g6h8i0j2k4l6m8n/o0p2q4r6s8t/u1v3w5x7y9z/A2B4C6D8E0F2G4H6I8J0K2L4M6N8O+P0Q2R4S6T8U0V2W4X6Y8Z0a2b4c6d8e0f2g4h6i8j0k2l4m6n8o/p0q2r4s6t8u/v1w3x5y7z9A/B2C4D6E8F0G2H4I6J8K0L2M4N6O8P+Q0R2S4T6U8V0W2X4Y6Z8a0b2c4d6e8f0g2h4i6j8k0l2m4n6o8p/q0r2s4t6u8v/w1x3y5z7A9B/C2D4E6F8G0H2I4J6K8L0M2N4O6P8Q+R0S2T4U6V8W0X2Y4Z6a8b0c2d4e6f8g0h2i4j6k8l+m0n2o4p6q8r/s1t3u5v7w9x/y2z4A6B8C0D2E4F6G8H0I2J4K6L8M+N0O2P4Q6R8S0T2U4V6W8X0Y2Z4a6b8c0d2e4f6g8h0i2j4k6l8m/n0o2p4q6r8s/t1u3v5w7x9y/z2A4B6C8D0E2F4G6H8I0J2K4L6M8N+O0P2Q4R6S8T0U2V4W6X8Y0Z2a4b6c8d0e2f4g6h8i0j2k4l6m8n/o0p2q4r6s8t/u1v3w5x7y9z/A2B4C6D8E0F2G4H6I8J0K2L4M6N8O+P0Q2R4S6T8U0V2W4X6Y8Z0a2b4c6d8e0f2g4h6i8j0k2l4m6n8o/p0q2r4s6t8u/v1w3x5y7z9A/B2C4D6E8F0G2H4I6J8K0L2M4N6O8P+Q0R2S4T6U8V0W2X4Y6Z8a0b2c4d6e8f0g2h4i6j8k0l2m4n6o8p/q==";

    // 从配置文件注入令牌过期时间
    private long jwtExpiration = 1000 * 60 * 60; // 60分钟

    /**
     * 生成令牌（登录成功时调用）
     * @param id 用户ID（从数据库查询的唯一标识）
     * @param userType 用户类型（USER/MERCHANT/ADMIN）
     * @return 生成的JWT令牌字符串
     */
    // 生成令牌（包含用户ID和用户类型）
    public String generateToken(Long id, String userType) {
        Date expireDate = new Date(System.currentTimeMillis() + jwtExpiration);
        return Jwts.builder()
                .setSubject(id.toString()) // 存储用户ID（对应表的主键）
                .claim("userType", userType) // 存储用户类型（USER/MERCHANT/ADMIN）
                .setIssuedAt(new Date())
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, jwtSecret)
                .compact();
    }

    // 从令牌中解析用户类型
    public String getUserTypeFromToken(String token) {
        Claims claims = validateToken(token);
        if (claims == null) {
            return null;
        }
        return claims.get("userType", String.class);
    }

    /**
     * 验证令牌有效性
     * @param token 前端传入的令牌字符串
     * @return 令牌中的声明（包含用户ID等信息），验证失败返回null
     */
    public Claims validateToken(String token) {
        try {
            // 解析令牌并验证签名和过期时间
            return Jwts.parserBuilder()
                    .setSigningKey(jwtSecret)  // 使用配置的密钥验证签名
                    .build()
                    .parseClaimsJws(token)     // 解析令牌
                    .getBody();                // 获取令牌中的数据（Claims）
        } catch (ExpiredJwtException e) {
            // 令牌已过期
            System.out.println("JWT令牌已过期：" + e.getMessage());
        } catch (SignatureException e) {
            // 签名验证失败（令牌被篡改）
            System.out.println("JWT签名错误（可能被篡改）：" + e.getMessage());
        } catch (MalformedJwtException e) {
            // 令牌格式错误（非JWT格式）
            System.out.println("JWT格式错误：" + e.getMessage());
        } catch (IllegalArgumentException e) {
            // 令牌为空或参数错误
            System.out.println("JWT令牌为空或参数错误：" + e.getMessage());
        }
        return null;  // 验证失败返回null
    }

    /**
     * 从令牌中解析用户ID（需先验证令牌有效）
     * @param token 前端传入的令牌字符串
     * @return 用户ID（验证失败返回null）
     */
    public Long getUserIdFromToken(String token) {
        Claims claims = validateToken(token);
        if (claims == null) {
            return null;  // 令牌无效，返回null
        }
        // 从令牌的Subject中获取用户ID（生成时存储的是字符串，需转为Long）
        return Long.parseLong(claims.getSubject());
    }
}